/*
**  Copyright (C), CHENGDU GONGWEI TECHNOLOGY CO.,LTD.
**
**  Project:	Manager Unit v1.0
**  File:    	
**  Author: 	zhaozhuyu
**  Date:    	2017/05/20
**
**  Purpose:
**    		.
**
**  History: 
**  <author>   <time>          <version >   <desc>
*	$$Author$$
*/


/* Include files. */
extern "C" { 
	#include "standard.h"
	#include "util.h"
	#include "debug.h"
	#include "alreadyrun.h"
}

#include "subsystemcore.h"
#include "network.h"
#include "child.h"
#include "script.h"
#include "timercore.h"
#include "message.h"
#include "taskcore.h"
#include "ubusmgr.h"

/* Local function declarations. */

/* Macro API definitions. */

#define MAX_FILE_HANDLE 1048576

/* Global variable declarations. */

#ifdef U_LOOP
struct uloop_timeout script_uloop_handle = {0};
#else
struct ev_loop *main_loop;
#endif

/* Type definitions. */

/* Local function definitions. */

int sigign() 
{
	struct sigaction sa;
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &sa, NULL);

/*
* ignores the signal of SIGTTOU when MU runs in background
* though which is not reasonable for it under linux.
* by Bob@TW@19:30-2018-01-31
*/
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = SIG_IGN;
	sigaction(SIGTTOU, &sa, NULL);

	return 0;
}

#ifdef U_LOOP
void loopPrepareCb(struct uloop_timeout *w)
#else
void loopPrepareCb(struct ev_loop *loop, ev_prepare *w, int revents)
#endif
{
	while (!subSystem::message_queue.empty()){
		subSystem *sub = subSystem::message_queue.front();
		subSystem::message_queue.pop();
		if(sub->_msg_queue.size()){
			message *msg = sub->_msg_queue.front();
			sub->_msg_queue.pop();
			u64 cpu = currentMsTime();
			dispatch(sub, msg->_from.c_str(), msg->_to.c_str(), 
				msg->_session, msg->_type.c_str(), msg->_msg.c_str());
			sub->_cost_cpu += (currentMsTime() - cpu);
			message::destroy(msg);
		}
	}
}

void setLimitied()
{
	struct rlimit rlim = {MAX_FILE_HANDLE, MAX_FILE_HANDLE};
	
	if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
		ERROR("set setLimitied faild\n");
	}
	
 	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
		DEBUG("file max %u, %u\n", rlim.rlim_cur, rlim.rlim_max);	
 	}
	else {
		ERROR("get setLimitied faild\n");
	}
}

void setEnvs(lua_State *L)
{
	lua_getglobal(L, "package");
	lua_pushstring(L, "path");
	lua_pushstring(L, "/usr/local/share/lua/5.3/mu/?.lua;/usr/local/share/lua/5.3/?.lua;/sbin/script/?.lua");
    lua_settable(L, -3);
	lua_pushstring(L, "cpath");
	lua_pushstring(L, "/usr/local/lib/lua/5.3/mu/?.so;/usr/local/lib/lua/5.3/?.so;");
    lua_settable(L, -3);
	lua_pop(L, 1);
}

int main(int argc, char *argv[])
{
	if (alreadyRunning(argv[0])) {
		ERROR("%s is already running...\n", argv[0]);
		exit(0);
	}

	debugChange();
	sigign();
	setLimitied();
	
	const char * configfile = NULL ;
	
	if (argc > 1) {
		configfile = argv[1];
	} else {
		configfile = "./config";
	}

	createChildProcess();
	
#ifdef U_LOOP
	uloop_init();
#else
	main_loop = ev_loop_new(EVBACKEND_EPOLL);
#endif

	recvScriptResult();

	subSystem *sub = NULL;
	lua_State *L;
	if(NULL == (L = luaL_newstate())){  
		ERROR("%s\n", lua_tostring(L, -1));
		goto end;  
	} 
	
	luaL_openlibs(L);   
	setEnvs(L);
	int err;
	if((err = luaL_loadfile(L, "./script/main.lua"))){  
		ERROR("%s\n", lua_tostring(L, -1));
		goto end;
	}
	ASSERT(err == LUA_OK);
	sub = new subSystem(string("main"), L);
	lua_pushlightuserdata(L, sub);
	lua_setfield(L, LUA_REGISTRYINDEX, "sub");
	lua_pushcfunction(L, traceback);
	lua_insert(L, 1);
	err = lua_pcall(L, 0, 0, 1);	
	if (err != LUA_OK){
		ERROR("%s\n", lua_tostring(L, -1));
		goto end;
	}
	lua_settop(L, 0);
	delete sub;

#ifdef U_LOOP
	createServiceServer();
	script_uloop_handle.cb = loopPrepareCb;
	uloop_timeout_set(&script_uloop_handle, 1);

	uloop_run();
	uloop_done();
#else
	createServiceServer(main_loop);

	ev_prepare prepare;
	ev_prepare_init (&prepare, loopPrepareCb);
	ev_prepare_start (main_loop, &prepare);
	
	ev_run(main_loop);
	ev_loop_destroy(main_loop);
#endif
	ERROR("out main loop\n");	
	
end:
	ERROR("main over!\n");
	return -1;
}




